﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ProceduralCity.Models
{
    class Ground
    {
        TexturedQuad[] surface;
        Texture2D[] surfaceTextures;

        public Ground(Vector3 farLeft, int lotsWide, int lotsDeep, float lotWidth, float lotDepth, float gap)
        {
            farLeft.X -= gap / 2;
            farLeft.Z -= gap / 2;

            int lightSize = 2;
            int lightGap = 10;
            Texture2D lotTexture = GenerateLotTexture((int)lotWidth, (int)lotDepth, (int)gap, lightSize, lightGap, Color.LightGoldenrodYellow);

            surface = new TexturedQuad[lotsWide * lotsDeep];
            surfaceTextures = new Texture2D[lotsWide * lotsDeep];
            for (int row = 0; row < lotsDeep; ++row)
            {
                for (int col = 0; col < lotsWide; ++col)
                {
                    // get lot corner position
                    Vector3 lotPosition;
                    lotPosition.X = farLeft.X + col * (lotWidth + gap);
                    lotPosition.Y = 0;
                    lotPosition.Z = farLeft.Z + row * (lotDepth + gap);

                    int index = row * lotsWide + col;
                    surface[index] = new TexturedQuad(lotPosition, Vector3.Up, Vector3.Forward, lotWidth + gap, lotDepth + gap);
                    surfaceTextures[index] = lotTexture;
                }
            }
        }

        public void Draw(GraphicsDevice device, BasicEffect groundEffect)
        {
            for (int i = 0; i < surface.Length; ++i)
            {
                TexturedQuad quad = surface[i];
                groundEffect.Texture = surfaceTextures[i];

                foreach (EffectPass pass in groundEffect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
                        quad.Vertices, 0, quad.Vertices.Length,
                        quad.Indices, 0, quad.Indices.Length / 3);
                }
            }
        }

        private Texture2D GenerateLotTexture(int lotWidth, int lotDepth, int gap, int lightSize, int lightGap, Color lightColor)
        {
            int totalWidth = lotWidth + gap;
            int totalDepth = lotDepth + gap;
            Color[] colorData = new Color[totalWidth * totalDepth];
            for (int i = 0; i < totalWidth * totalDepth; ++i)
                colorData[i] = Color.Black;

            float lightInsetPercent = 0.25f;
            int lightInsetPixels = (int)(lightInsetPercent * gap);

            int farRow = lightInsetPixels;
            int nearRow = lotDepth + gap - lightInsetPixels;
            int leftCol = lightInsetPixels;
            int rightCol = lotWidth + gap - lightInsetPixels;

            // horizontal lights
            for (int col = lightInsetPixels; col <= rightCol; col += lightGap)
            {
                for (int r = 0; r < lightSize; ++r)
                {
                    for (int c = 0; c < lightSize; ++c)
                    {
                        colorData[(farRow + r) * totalWidth + col + c] = lightColor;
                        colorData[(nearRow + r) * totalWidth + col + c] = lightColor;
                    }
                }
            }

            // vertical lights
            for (int row = lightInsetPixels + lightGap; row < nearRow; row += lightGap)
            {
                for (int r = 0; r < lightSize; ++r)
                {
                    for (int c = 0; c < lightSize; ++c)
                    {
                        colorData[(row + r) * totalWidth + leftCol + c] = lightColor;
                        colorData[(row + r) * totalWidth + rightCol + c] = lightColor;
                    }
                }
            }

            Texture2D texture = new Texture2D(Game.graphics.GraphicsDevice, totalWidth, totalDepth);
            texture.SetData(colorData);
            return texture;
        }
    }
}
